﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Pay.Core;
using Pay.DTO;
using Pay.DTO.hniao;
using Pay.Data;
using Pay.TO;
using Newtonsoft.Json.Linq;

namespace Pay.Service {
    /// <summary>
    /// 候鸟统一解析业务接口
    /// </summary>
    public interface IHniaoLogic {
        Task<HniaoReturn> Handler(string requsetData, PayContext context);
    }
    public class HniaoBase {
        protected string tag { get; set; }
        protected ILogHelper log {
            get {
                return IocHelper.Get<ILogHelper>("info");
            }
        }
        protected HniaoReturn hniaoReturn { get; set; }
        public HniaoBase() {
            hniaoReturn = new HniaoReturn();
        }
    }
    public class HniaoReturn {
        public HniaoReturn() {
            messages = new List<message_push_dto>();
        }
        public string tag { get; set; }
        public bool is_push { get; set; }
        public List<message_push_dto> messages { get; set; }
    }
    /// <summary>
    /// 商品上架
    /// </summary>
    public class GoodsShelve : HniaoBase, IHniaoLogic {
        public async Task<HniaoReturn> Handler(string requsetData, PayContext context) {
            var goods = requsetData.ToObject<hn_goods_op>();
            var product = context.Products.FirstOrDefault(c => c.Sku == goods.goodsSku && c.IsHtl == 2);
            if (product == null) {
                log.Info(string.Format("候鸟商品名称：{0},sku:{1},不存在！商品信息：{2}", goods.goodsName, goods.goodsSku, goods.ToJson()));
                return hniaoReturn;
            }
            //if (product.SaleStatus != SaleStatus.Sell) {
            //    product.SaleStatus = SaleStatus.OutOfStock;
            //    hniaoReturn.tag = "Product" + product.Id;
            //}
            return await Task.FromResult(hniaoReturn);
        }
    }
    /// <summary>
    /// 商品下架
    /// </summary>
    public class GoodsUnShelve : HniaoBase, IHniaoLogic {
        public async Task<HniaoReturn> Handler(string requsetData, PayContext context) {
            var goods = requsetData.ToObject<hn_goods_op>();
            var product = context.Products.FirstOrDefault(c => c.Sku == goods.goodsSku && c.IsHtl == 2);
            if (product == null) {
                log.Info(string.Format("候鸟商品名称：{0},sku:{1},不存在！商品信息：{2}", goods.goodsName, goods.goodsSku, goods.ToJson()));
                return await Task.FromResult(hniaoReturn);
            }
            product.SaleStatus = SaleStatus.Delete;
            product.ShortDescription = "候鸟推送商品下架";
            hniaoReturn.tag = string.Format("Product{0}", product.Id);
            return await Task.FromResult(hniaoReturn);
        }
    }
    /// <summary>
    /// 商品价格变更
    /// </summary>
    public class GoodsPrice : HniaoBase, IHniaoLogic {
        public async Task<HniaoReturn> Handler(string requsetData, PayContext context) {
            var goods = requsetData.ToObject<hn_goods_price_notify>();
            var product = context.Products.FirstOrDefault(c => c.Sku == goods.goodsSku && c.IsHtl == 2);
            if (product == null) {
                log.Info(string.Format("候鸟商品名称：{0},sku:{1},不存在！商品信息：{2}", goods.goodsName, goods.goodsSku, goods.ToJson()));
                return await Task.FromResult(hniaoReturn);
            }

            var goods_price_req = new hn_goods_price_req {
                goodsSku = goods.goodsSku
            };
            var result = await new HniaoMallSign().HniaoReq<hn_goods_price_res>(goods_price_req);
            foreach (var spec in result.data) {
                foreach (var spec_detail in spec.specDetail) {
                    decimal cost_price = decimal.Parse(spec_detail.specPrice);
                    //if (!IsExistSpec(product, spec.specGroupName, spec_detail)) {
                    //    context.ProductSkus.Add(new ProductSku {
                    //        ProductId = product.Id,
                    //        SkuName = spec_detail.specName,
                    //        SkuPath = string.Format("{0}-{1}", spec.specGroupName, spec_detail.specNum),
                    //        Price = cost_price * 1.2M,
                    //        CostPrice = cost_price,
                    //        Weight = 0,
                    //        StartExpDate = spec.startExpDate,
                    //        EndExpDate = spec.endExpDate,
                    //        Stock = 0
                    //    });
                    //}
                    if (cost_price > product.CostPrice && spec_detail.specNum == 1) {
                        product.SaleStatus = SaleStatus.OutOfStock;
                        product.ShortDescription = "候鸟价格变动，自动下架";
                    }
                }
            }
            hniaoReturn.tag = string.Format("Product{0}", product.Id);
            return await Task.FromResult(hniaoReturn);
        }
        private bool IsExistSpec(Product product, string specGroupName, hn_spec_detail spec_detail) {
            bool result = false;
            var skus = product.ProductSkus.ToList();
            foreach (var sku in skus) {
                DateTime dt = DateTime.Now;
                DateTime dt1 = DateTime.Now;
                int temp_spec = 0;
                decimal cost_price = 0;
                string temp = sku.SkuPath.Substring(sku.SkuPath.LastIndexOf('-') + 1);
                if (!int.TryParse(temp, out temp_spec)) continue;
                string temp_time = sku.SkuPath.Substring(0, sku.SkuPath.LastIndexOf('-'));
                if (specGroupName.Contains("-")) {
                    var groups = specGroupName.Split('-');
                    var temp_skus = temp_time.Split('-');
                    if (temp_skus.Length <= 0) continue;
                    if (DateTime.TryParse(groups[0], out dt) && DateTime.TryParse(groups[1], out dt1)) {
                        if (dt != dt1) continue;
                    }
                    if (DateTime.TryParse(temp_skus[0], out dt) && DateTime.TryParse(temp_skus[1], out dt1)) {
                        if (dt != dt1) continue;
                    }
                } else if (DateTime.TryParse(specGroupName, out dt) && DateTime.TryParse(temp_time, out dt1)) {
                    if (dt != dt1) continue;
                } else if (temp_time != specGroupName) {
                    continue;
                }
                if (temp_spec == spec_detail.specNum) {
                    if (!decimal.TryParse(spec_detail.specPrice, out cost_price)) continue;
                    if (cost_price > sku.CostPrice) {
                        product.SaleStatus = SaleStatus.OutOfStock;
                        product.ShortDescription = "候鸟价格变更成本价大于商城设置销售价，强制下架";
                    }
                    sku.CostPrice = cost_price;
                    result = true;
                    break;
                }
            }
            return result;
        }
    }
    /// <summary>
    /// 商品发货
    /// </summary>
    public class GoodsDelivery : HniaoBase, IHniaoLogic {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="requsetData"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task<HniaoReturn> Handler(string requsetData, PayContext context) {
            var delivery = requsetData.ToObject<hn_order_express_notify>();
            var order = context.Orders.FirstOrDefault(c => c.OrderNo == delivery.orderNo);
            if (order == null) {
                log.Info(string.Format("候鸟订单号：{0}不存在！物流信息：{1}", delivery.orderNo, delivery.ToJson()));
                return await Task.FromResult(hniaoReturn);
            }
            order.Status = OrderStatus.Confirm;
            order.Shipping.ExpressCompanyName = delivery.expressName;
            order.Shipping.ExpressNo = StringHelper.ReplaceExpressCode(delivery.expressCode);
            order.Shipping.ShipOrderNumber = delivery.expressNo;
            hniaoReturn.tag = order.BuyId.HasValue ? "Orders" + order.BuyId : "";
            var msg = context.Settings.FirstOrDefault(c => c.Id == 1).Settings.ToObject<setting_dto>().msg.FirstOrDefault(c => c.code == "order_delivery");
            if (msg == null)
                throw new ServerErrorException("发货消息未配置");
            string product_name = order.OrderItems.First().ProductName;
            var buyerMessage = new MessagePush();
            if (order.BuyId > 0) {
                hniaoReturn.is_push = true;
                buyerMessage.MerchantId = order.BuyId.Value;
                buyerMessage.Type = MsgType.OrderSellerDeliver;
                buyerMessage.Title = msg.name;
                buyerMessage.ShortContent = order.Buyer.Mobile;
                buyerMessage.Content = string.Format(msg.content, product_name, delivery.expressNo);
                buyerMessage.Ext = "{}";
                buyerMessage.CreateTime = DateTime.Now.ToUnix();
                buyerMessage.ObjectId = order.Id;
                context.MessagePushs.Add(buyerMessage);
                hniaoReturn.messages.Add(buyerMessage.ToDtoObject<message_push_dto>());
                //if (order.ShopId > 0) {
                //    var shopinfo = context.ShopInfo.FirstOrDefault(c => c.Id == order.ShopId);
                //    var message = new MessagePush();
                //    buyerMessage.ToCopyProperty(message);
                //    message.MerchantId = shopinfo.Id;
                //    message.ShortContent = shopinfo.Merchant.Mobile;
                //    message.ObjectId = shopinfo.Id;
                //    context.MessagePushs.Add(message);
                //    hniaoReturn.messages.Add(message.ToDtoObject<message_push_dto>());
                //}
            }
            return await Task.FromResult(hniaoReturn);
        }
    }
    /// <summary>
    /// 商品新增
    /// </summary>
    public class GoodsAdd : HniaoBase, IHniaoLogic {
        public async Task<HniaoReturn> Handler(string requsetData, PayContext context) {
            var notify = requsetData.ToObject<hn_goods_op_notify>();
            bool has_goods = context.Products.Any(c => c.Sku == notify.goodsSku && c.IsHtl == 2);
            if (!has_goods) {
                var req = new hn_goods_op_req {
                    goodsSku = notify.goodsSku
                };
                var merchant = context.Merchants.FirstOrDefault(c => c.MerchantNo == RequestMethod.HNIAO_NO);
                var result = await new HniaoMallSign().HniaoReq<hn_goods_op_res>(req);
                if (result.data.goodsDetail != null) {
                    var products = new List<Product>();
                    var unixTime = DateTime.Now.ToUnix();
                    decimal max_price = 0;
                    var product = new Data.Product {
                        MerchantId = merchant.Id,
                        Sku = result.data.goodsDetail.sku,
                        Props = "[]",
                        TradeType = result.data.goodsDetail.tradeType,
                        Code = result.data.goodsDetail.barcode,
                        Name = result.data.goodsDetail.goodsName,
                        Description = string.IsNullOrEmpty(result.data.goodsDetail.description) ? "" : StringHelper.StringToImgUrl(WebHelper.HtmlDecode(result.data.goodsDetail.description), RequestMethod.HNIAO_DOMAIN),
                        BrandsName = result.data.goodsDetail.brand,
                        Country = result.data.goodsDetail.origin,
                        SaleStatus = SaleStatus.OutOfStock,
                        AuditStatus = AuditStatus.PendingAudit,
                        IsHtl = 2,
                        CreateTime = unixTime,
                        UpdateTime = unixTime
                    };
                    product.ImagePath = (string.IsNullOrEmpty(result.data.goodsDetail.big) ? "" : string.Format("[\"{0}/{1}\"]", RequestMethod.HNIAO_DOMAIN, result.data.goodsDetail.big));
                    product.MainImageUrl = (string.IsNullOrEmpty(result.data.goodsDetail.big) ? "" : string.Format("{0}/{1}", RequestMethod.HNIAO_DOMAIN, result.data.goodsDetail.big));
                    if (result.data.goodsDetail.spec != null) {
                        var item = JObject.Parse(result.data.goodsDetail.spec.ToJson());
                        var collection = item.ToObject<SortedDictionary<string, object>>();
                        foreach (var kv in collection) {
                            if (kv.Value is JArray) {
                                var arrs = kv.Value as JArray;
                                foreach (var spec in arrs) {
                                    var goods_spec = spec.ToObject<hn_goods_spec>();
                                    if (goods_spec.specPrice > max_price && goods_spec.specNum == 1) {
                                        product.Price = goods_spec.specPrice * 1.2M;
                                        product.CostPrice = goods_spec.specPrice;
                                        product.Stock = goods_spec.stock;
                                        max_price = goods_spec.specPrice;
                                    }
                                }
                            }
                        }
                        products.Add(product);
                    }
                    if (products.Count > 0)
                        context.Products.AddRange(products);
                }
            }
            return hniaoReturn;
        }
    }
    /// <summary>
    /// 商品更新
    /// </summary>
    public class GoodsEdit : HniaoBase, IHniaoLogic {
        public async Task<HniaoReturn> Handler(string requsetData, PayContext context) {
            var notify = requsetData.ToObject<hn_goods_op_notify>();
            bool has_goods = context.Products.Any(c => c.Sku == notify.goodsSku && c.IsHtl == 2);
            if (has_goods) {
                var req = new hn_goods_op_req {
                    goodsSku = notify.goodsSku
                };
                var result = await new HniaoMallSign().HniaoReq<hn_goods_op_res>(req);
                if (result.data != null) {
                    var goods = context.Products.FirstOrDefault(c => c.Sku == notify.goodsSku);
                    goods.Name = result.data.goodsDetail.goodsName;
                    goods.MainImageUrl = (string.IsNullOrEmpty(result.data.goodsDetail.big) ? "" : string.Format("{0}/{1}", RequestMethod.HNIAO_DOMAIN, result.data.goodsDetail.big));
                    goods.Description = string.IsNullOrEmpty(result.data.goodsDetail.description) ? "" : StringHelper.StringToImgUrl(WebHelper.HtmlDecode(result.data.goodsDetail.description), RequestMethod.HNIAO_DOMAIN);
                    if (result.data.goodsDetail.spec != null) {
                        var item = JObject.Parse(result.data.goodsDetail.spec.ToJson());
                        var collection = item.ToObject<SortedDictionary<string, object>>();
                        foreach (var kv in collection) {
                            //if (kv.Value is JArray) {
                            //    var arrs = kv.Value as JArray;
                            //    foreach (var spec in arrs) {
                            //        var goods_spec = spec.ToObject<hn_goods_spec>();
                            //        string skupath = string.Format("{0}-{1}", kv.Key, goods_spec.specNum);
                            //        var sku = goods.ProductSkus.FirstOrDefault(c => c.SkuPath == skupath);
                            //        if (sku != null) {
                            //            sku.StartExpDate = goods_spec.startExpDate;
                            //            sku.EndExpDate = goods_spec.endExpDate;
                            //        }
                            //    }
                            //}
                        }
                    }
                    hniaoReturn.tag = string.Format("Product{0}", goods.Id);
                }
            }
            return hniaoReturn;
        }
    }
    /// <summary>
    /// 商品库存变更
    /// </summary>
    public class GoodsStock : HniaoBase, IHniaoLogic {
        public async Task<HniaoReturn> Handler(string requsetData, PayContext context) {
            var notify = requsetData.ToObject<hn_goods_op_notify>();
            bool has_goods = context.Products.Any(c => c.Sku == notify.goodsSku && c.IsHtl == 2);
            if (has_goods) {
                var req = new hn_goods_stock_req {
                    goodsSku = notify.goodsSku
                };
                var skus = new List<ProductSku>();
                var result = await new HniaoMallSign().HniaoReq<hn_goods_stock_res>(req);
                if (result.data != null) {
                    var goods = context.Products.FirstOrDefault(c => c.Sku == notify.goodsSku && c.IsHtl == 2);
                    foreach (var spec in result.data) {
                        //skus = goods.ProductSkus.ToList();
                        //foreach (var sku in skus) {
                        //    if (IsEqualGroupName(sku.SkuPath, spec.specGroupName)) {
                        //        var arrs = sku.SkuPath.Split('-');
                        //        sku.StartExpDate = spec.startExpDate;
                        //        sku.EndExpDate = spec.endExpDate;
                        //        if (arrs.Length == 2) {
                        //            sku.Stock = spec.stockNum / int.Parse(arrs[1]);
                        //        } else if (arrs.Length == 3) {
                        //            sku.Stock = spec.stockNum / int.Parse(arrs[2]);
                        //        }
                        //    }
                        //}
                        if (spec.stockNum == 0) {
                            goods.SaleStatus = SaleStatus.OutOfStock;
                            hniaoReturn.tag = string.Format("Product{0}", goods.Id);
                        }
                    }
                }
            }
            return hniaoReturn;
        }

        private bool IsEqualGroupName(string sku_path, string specGroupName) {
            bool result = false;
            DateTime dt = DateTime.Now;
            DateTime dt1 = DateTime.Now;
            string temp_time = sku_path.Substring(0, sku_path.LastIndexOf('-'));
            if (specGroupName.Contains("-")) {
                var groups = specGroupName.Split('-');
                var skus = temp_time.Split('-');
                if (skus.Length <= 0) return result;
                if (!DateTime.TryParse(groups[0], out dt))
                    return result;
                if (!DateTime.TryParse(groups[1], out dt1))
                    return result;
                if (dt != dt1) return result;
                if (!DateTime.TryParse(skus[0], out dt))
                    return result;
                if (!DateTime.TryParse(skus[1], out dt1))
                    return result;
                if (dt != dt1) return result;
                result = true;
            } else if (DateTime.TryParse(specGroupName, out dt)) {
                result = DateTime.TryParse(temp_time, out dt1);
                if (dt == dt1) result = true;
            } else if (temp_time == specGroupName) {
                result = true;
            }
            return result;
        }
    }

    public class HniaoLogicFade {
        private readonly static Dictionary<string, IHniaoLogic> logics = new Dictionary<string, IHniaoLogic> {
            { "goods.shelve",new GoodsShelve()},
            { "goods.unshelve",new GoodsUnShelve()},
            { "goods.price",new GoodsPrice()},
            { "order.delivery",new GoodsDelivery()},
            { "goods.add",new GoodsAdd()},
            { "goods.edit",new GoodsEdit()},
            { "goods.stock",new GoodsStock()}
        };
        public static async Task<HniaoReturn> AnalysisLogic(pay_html_dto pay_html, PayContext context) {
            var notify = pay_html.html.ToObject<hn_notify_base>();
            string requestData = WebHelper.UrlDecode(notify.requestData);
            var req = requestData.ToObject<hn_goods_notify>();
            IHniaoLogic logic = logics[notify.requestType];
            return await logic.Handler(req.data.ToString(), context);
        }
    }
}
